package com.easy.service.impl;

import com.easy.bean.Attraction;
import com.easy.bean.Itinerary;
import com.easy.bean.Itinerary_detail;
import com.easy.mapper.AttractionDao;
import com.easy.mapper.ItineraryDao;
import com.easy.mapper.Itinerary_detailDao;
import com.easy.service.ItineraryService;
import com.easy.util.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class ItineraryServiceImpl implements ItineraryService {

    private static final String CACHE_NAME = "itinerary";

    @Autowired
    ItineraryDao itineraryDao;

    @Autowired
    Itinerary_detailDao itineraryDetailDao;

    @Autowired
    AttractionDao attractionDao;

    @Override
    @CacheEvict(value = CACHE_NAME, key = "'itinerary:' + #p0.id", condition = "#result != null")
    public Itinerary add(Itinerary itinerary) {
        // 新增数据
        itineraryDao.add(itinerary);
        // 通过主键查询数据库的数据
        Itinerary result = itineraryDao.one(itinerary.getId());
        return result;
    }

    @Override
    @CacheEvict(value = CACHE_NAME, key = "'itinerary:id:' + #p0")
    public int del(Integer id) {
        return itineraryDao.del(id);
    }

    @Override
    @CacheEvict(value = CACHE_NAME, key = "'itinerary:' + #p0.id", condition = "#p0 != null and #p0.id != null")
    public Itinerary edit(Itinerary itinerary) {
        itineraryDao.edit(itinerary);
        Itinerary result = itineraryDao.one(itinerary.getId());
        return result;
    }

    @Override
    @Cacheable(value = CACHE_NAME, key = "'itinerary:list:' + T(java.util.Objects).hash(#p0)", unless = "#result == null or #result.isEmpty()")
    public List<Itinerary> all(Itinerary itinerary) {
        return itineraryDao.all(itinerary);
    }

    @Override
    @Cacheable(value = CACHE_NAME, key = "'itinerary:id:' + #p0", unless = "#result == null")
    public Itinerary one(Integer id) {
        return itineraryDao.one(id);
    }

    @Override
    public void page(Page page, Itinerary itinerary) {
        int count = itineraryDao.pageCount(itinerary);
        Object data = itineraryDao.page(page, itinerary);
        page.setCount(count);
        page.setData(data);
    }

    @Override

    public void pageWithDetails(Page page, Itinerary itinerary) {
        int count = itineraryDao.pageCountWithDetails(itinerary);
        Object data = itineraryDao.pageWithDetails(page, itinerary);
        page.setCount(count);
        page.setData(data);
    }
    @Override


    public List<Itinerary_detail> getDetails(Integer itinerary_id) {
        return itineraryDao.getDetails(itinerary_id);
    }

    @Override

    public Itinerary generateItinerary(Integer userId, String city, Integer days, String preferences) {
        // 创建行程主表
        Itinerary itinerary = new Itinerary();
        itinerary.setUser_id(userId);
        itinerary.setCity(city);
        itinerary.setDays(days);
        itinerary.setPreferences(preferences);
        itinerary.setStart_date(LocalDate.now());

        // 添加行程主表记录
        itineraryDao.add(itinerary);

        // 根据偏好和天数生成详细行程
        generateItineraryDetails(itinerary, preferences, days);

        return itineraryDao.one(itinerary.getId());
    }

    private void generateItineraryDetails(Itinerary itinerary, String preferences, Integer days) {
        // 查询符合条件的景点
        Attraction queryAttraction = new Attraction();
        queryAttraction.setCity(itinerary.getCity());
        List<Attraction> attractions = attractionDao.all(queryAttraction);

        // 如果有偏好设置，进一步筛选景点
        List<Attraction> filteredAttractions = new ArrayList<>();
        if (preferences != null && !preferences.isEmpty()) {
            for (Attraction attraction : attractions) {
                if (attraction.getType() != null && attraction.getType().contains(preferences)) {
                    filteredAttractions.add(attraction);
                } else if (attraction.getName() != null && attraction.getName().contains(preferences)) {
                    filteredAttractions.add(attraction);
                }
            }
        } else {
            filteredAttractions = attractions;
        }

        // 如果筛选后没有景点或景点不足，则使用所有景点
        if (filteredAttractions.isEmpty()) {
            filteredAttractions = attractions;
        }

        // 记录已使用的景点，防止在同一个行程中重复
        Set<Integer> usedAttractionIds = new HashSet<>();
        // 创建一个可用景点列表副本
        List<Attraction> availableAttractions = new ArrayList<>(filteredAttractions);

        // 为每一天分配景点
        Random random = new Random();
        for (int day = 1; day <= days; day++) {
            // 每天分配3-4个景点
            int attractionsPerDay = 3 + random.nextInt(2);

            // 如果可用景点数量不足，调整当天景点数量
            if (availableAttractions.size() < attractionsPerDay) {
                attractionsPerDay = Math.max(1, availableAttractions.size());
            }

            for (int i = 0; i < attractionsPerDay && !availableAttractions.isEmpty(); i++) {
                // 选择第一个可用的景点（因为我们已经打乱了顺序）
                Attraction selectedAttraction = availableAttractions.remove(0);

                // 记录该景点已被使用
                usedAttractionIds.add(selectedAttraction.getId());

                // 创建行程详情
                Itinerary_detail detail = new Itinerary_detail();
                detail.setItinerary_id(itinerary.getId());
                detail.setDay_number(day);
                detail.setAttraction_id(selectedAttraction.getId());

                // 设置游览时间 (每3小时一个景点，中午12-13点休息)
                int hour = 9 + (i * 3); // 上午9点开始
                // 如果时间超过了12点，需要跳过午休时间
                if (hour >= 12) {
                    hour += 1; // 跳过12-13点的午休时间
                }
                detail.setVisit_time(hour + ":00");

                // 根据景点类型设置不同的备注
                String notes = generateNotesByAttractionType(selectedAttraction);
                detail.setNotes(notes);

                // 添加到数据库
                itineraryDetailDao.add(detail);
            }

            // 重新填充可用景点列表（同一个行程中不重复，但可以重新使用之前用过的景点）
            availableAttractions.clear();
            for (Attraction attraction : filteredAttractions) {
                if (!usedAttractionIds.contains(attraction.getId())) {
                    availableAttractions.add(attraction);
                }
            }

            // 如果所有景点都已使用过，重新开始一轮（清空使用记录）
            if (availableAttractions.isEmpty() && usedAttractionIds.size() == filteredAttractions.size()) {
                usedAttractionIds.clear();
                availableAttractions.addAll(filteredAttractions);
            }

            // 打乱顺序
            Collections.shuffle(availableAttractions);
        }
    }

    /**
     * 根据景点类型生成不同的备注
     * @param attraction 景点对象
     * @return 对应的备注信息
     */
    private String generateNotesByAttractionType(Attraction attraction) {
        String type = attraction.getType();
        if (type == null) {
            return "建议游览时间：2小时左右";
        }

        if (type.contains("风景区") || type.contains("公园") || type.contains("自然")) {
            return "自然风光类景点，建议预留2-3小时游览时间";
        } else if (type.contains("博物馆") || type.contains("展览") || type.contains("文化")) {
            return "文化展览类景点，建议预留2小时左右参观";
        } else if (type.contains("古迹") || type.contains("遗址") || type.contains("历史")) {
            return "历史文化类景点，建议预留1.5-2小时参观时间";
        } else if (type.contains("商业") || type.contains("街") || type.contains("购物")) {
            return "商业街区，可根据个人喜好安排时间";
        } else if (type.contains("宗教") || type.contains("寺庙")) {
            return "宗教场所，请遵守相关礼仪规范，建议游览1-2小时";
        } else if (type.contains("游乐园") || type.contains("娱乐")) {
            return "娱乐休闲场所，建议预留半天时间";
        } else {
            return "建议游览时间：2小时左右";
        }
    }
}